﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NLog;
using planerka.DataAccess.ViewModels;
using planerka.DataAccess.DataService;
using System.Web.Security;
using planerka.DataAccess.Models;
using planerka.Common;
using System.IO;
using System.Configuration;
using System.Web.Configuration;
using planerka.Common.Enums;
using LumenWorks.Framework.IO.Csv;
using System.Text;
using System.Web.Routing;

namespace planerka.Web.Controllers
{
    [Authorize]
    public class tmController : Controller
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        
        protected override void Initialize(RequestContext rc)
        {
            base.Initialize(rc);
            try
            {
                new UserService().initialyzeUserSettings();
            }
            catch { }
        }

        // 404
        protected override void HandleUnknownAction(string actionName)
        {
            try
            {
                this.View(actionName).ExecuteResult(this.ControllerContext);
            }
            catch (InvalidOperationException ieox)
            {
                ViewData["error"] = "Unknown Action: \"" +
                    Server.HtmlEncode(actionName) + "\"";
                ViewData["exMessage"] = ieox.Message;
                this.View("404").ExecuteResult(this.ControllerContext);
               
            }
        }  

        #region users

        // управление пользователями
        public ActionResult Users()
        {
            ViewData["resultMessage"] = TempData["resultMessage"];
            UserService userService = new UserService();
            usersViewModel uVM = new usersViewModel();
            
            userService.load_usersVMfilter(ref uVM); // чтение фильтра
            userService.fillUsersViewModel(ref uVM); // наполнение списка пользователей

            return View(uVM);
        }

        // редактировать, смотреть пользователя
        public ActionResult userDetails(long id)
        {
            user _user = new _Repository<user>().FindAll(p => p.ID == id).FirstOrDefault();

            if (_user == null)
            {
                TempData["resultMessage"] = "Нет такого пользователя";
                return RedirectToAction("Users");
            }

            return View(_user);
        }

        // редактировать, смотреть пользователя - post
        [HttpPost]
        public ActionResult userDetails(user _user)
        {
            if (!_user.rightsEdit)
            { 
                TempData["resultMessage"] = "Недостаточно прав для редактирования свойств пользователя";
                return RedirectToAction("Users");
            }
            
            #region pictures

            string saveFileName = "";
            // сохраним картинки
            foreach (string upload in Request.Files)
            {
                string tempPath = Server.MapPath("~/images/temp/");
                string imagesPath = Server.MapPath("~/images/photo/");
                string nailsPath = Server.MapPath("~/images/photo/nails/");

                var postedFile = Request.Files[upload];
                if (postedFile.ContentLength > 0)
                {
                    // очистим директорию с временными файлами
                    graphics.emptyDirectory(tempPath);

                    saveFileName = Guid.NewGuid().ToString() + ".jpg";

                    string filename = Path.GetFileName(Request.Files[upload].FileName);
                    // закачаем файл в директорию с временными файлами
                    Request.Files[upload].SaveAs(Path.Combine(tempPath, saveFileName));
                    
                    string resMessage = "";
                    graphics.savePicture(
                                Path.Combine(tempPath, saveFileName),
                                Path.Combine(imagesPath, saveFileName),
                                Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["imagesWidth"]),
                                0,
                                Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["imagesQuality"]),
                                ref resMessage);

                    graphics.savePicture(
                        Path.Combine(tempPath, saveFileName),
                        Path.Combine(nailsPath, saveFileName),
                        Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["imageNailsWidth"]),
                        0,
                        Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["nailsQuality"]),
                        ref resMessage);

                }
            }

            #endregion

            _Repository<user> userRepo = new _Repository<user>();
            user refItem = userRepo.FindAll(p => p.ID == _user.ID).FirstOrDefault();
            bool insert = false;
            if (refItem == null)
            {
                // создаем нового пользователя
                refItem = new user();
                insert = true;
            }

            try
            {

                UpdateModel(refItem);

                if (saveFileName != "")
                    refItem.photo = saveFileName;

                if (insert)
                    userRepo.InsertInstance(refItem);

                userRepo.Save();

                if (insert)
                {
                    UserService userService = new UserService();
                    long currentUser_ID = userService.getCurrentUser().ID;
                    // добавить пользователя в круг
                    Guid? resGuid = userService.createInvite(currentUser_ID);
                    userService.activateInvite(refItem.ID, (Guid)resGuid);
                }

                ViewData["resultMessage"] = "Сохранили данные";
                return View(refItem);
            }
            catch (Exception ex)
            {
                ViewData["resultMessage"] = "Ошибка сохранения данных";
                ExceptionUtility.LogException(logger, ex,
                    "[HttpPost] public ActionResult EditUser(user _user)",
                    "Ошибка сохранения USER_ID: " + _user.ID);
            }

            return View(refItem);
        }

        // редактировать пользователя
        public ActionResult CreateUser()
        {
            user _user = new user();
            _user.firstName = "";

            return View(_user);
        }

        // удалить пользователя
        public ActionResult DeleteUser(long id)
        {
            _Repository<user> userRepo = new _Repository<user>();
            user _user = userRepo.FindAll(p => p.ID == id).FirstOrDefault();

            if (_user == null)
            {
                TempData["resultMessage"] = "Нет такого пользователя";
            }
            else
            {
                if (_user.rightsDelete)
                {
                    try
                    {
                        userRepo.MarkForDeletion(_user);
                        userRepo.Save();
                    }
                    catch (Exception ex)
                    {
                        ExceptionUtility.LogException(logger, ex,
                    "public ActionResult DeleteUser(long id)",
                    "Ошибка удаления USER_ID: " + _user.ID);
                        TempData["resultMessage"] = "Ошибка удаления пользователя";
                    }
                }
                else
                    TempData["resultMessage"] = "Нельзя удалить этого пользователя";
            }

            return RedirectToAction("Users");
        }

        // отправить приглашение пользователю
        [HttpPost]
        public ActionResult sendInvite(string email)
        {
            // Создаем новый инвайт со своим Guid.
            // Приглашенный может зарегистрироваться только один раз
            // с любого email-адреса.
            
            
            UserService userService = new UserService();
            user currentUser = userService.getCurrentUser();
            Guid? resGuid = userService.createInvite(currentUser.ID);

            if (!EmailSMTP_Service.emailIsValid(email))
            {
                return Content("Неправильный email");
            }

            // есть такой пользователь в моем списке реальных пользователей?
            if (userService.getUserList(currentUser.UserId)
                .Where(p => p.email != null 
                    && p.email.ToLower().Trim() == email.ToLower().Trim() 
                    && p.isEmailApproved).Count() > 0)
            {
                return Content("Этот пользователь уже приглашен или имеется в вашем списке пользователей");
            }

            try
            {
                user me = new UserService().getCurrentUser();

                MessagesService messagesService = new MessagesService();
                List<SelectListItem> replaceItems = new List<SelectListItem>();
                replaceItems.Add(new SelectListItem { Text = "{RECEIVER_EMAIL}", Value = email });
                replaceItems.Add(new SelectListItem { Text = "{SENDER_FIO}", Value = me.surName + " " + me.firstName + " " + me.middleName });
                replaceItems.Add(new SelectListItem { Text = "{SENDER_EMAIL}", Value = me.email });
                replaceItems.Add(new SelectListItem { Text = "{CONFIRM_URL}", 
                    Value = ConfigurationManager.AppSettings["siteURL"].TrimEnd('/') 
                    + "/tm/account/acceptInvite/"
                    + resGuid.ToString() 
                });

                messagesService.sendTemplatedEmail(replaceItems, email, Common.Enums.MessageTypes.INVITE_USER);

                return Content("Приглашение отправлено...");
            }
            catch (Exception ex)
            {
                planerka.Common.ExceptionUtility.LogException(logger, ex,
                    "[POST] public ActionResult sendInviteReqest(string email)", "Ошибка отправки инвайта");
                return Content("Произошла ошибка");
            }
        }

        #endregion

        #region projects

        // список проектов
        public ActionResult projects()
        {
            ViewData["resultMessage"] = TempData["resultMessage"];
            ProjectService projectService = new ProjectService();
            projectsViewModel pVM = new projectsViewModel();

            projectService.load_projectsVMfilter(ref pVM); // чтение фильтра
            projectService.fillProjectsViewModel(ref pVM); // наполнение списка проектов
            projectService.addUserNamesToProjectsViewModel(ref pVM); // добавить словарь имен пользователей

            return View(pVM);
        }

        // обновить список проектов в соответствии с параметрами фильтра
        [HttpPost]
        public ActionResult projects(FormCollection formValues, string confirmButton)
        {
            long currentUser_ID = new UserService().getCurrentUser().ID;

            _Repository<userSetting> userSettingRepo = new _Repository<userSetting>();
            userSetting _userSetting = userSettingRepo.FindAll(p => p.user_ID == currentUser_ID).FirstOrDefault();
            if (_userSetting != null)
            {
                _userSetting.projects_customerID_filter = Convert.ToInt64(formValues["projects_customerID_filter"]);
                _userSetting.projects_ownerID_filter = Convert.ToInt64(formValues["projects_ownerID_filter"]);

                List<string> status_filter = new List<string>();
                for (int i = 1; i <= 4; i++)
                {
                    //projects_status
                    if (formValues["projects_status" + i].ToString() != "false")
                        status_filter.Add(i.ToString());
                }

                _userSetting.projects_status_filter = tools.getStringFromList(status_filter, ",");

                try
                {
                    userSettingRepo.Save();
                }
                catch (Exception ex)
                {
                    planerka.Common.ExceptionUtility.LogException(logger, ex,
                    "[POST] public ActionResult projects(FormCollection formValues, string confirmButton)", "Ошибка сохранения настроек пользователя");    
                }
            }

            return RedirectToAction("projects");
        }

        // создать проект
        public ActionResult CreateProject()
        {
            project _project = new project();
            _project.projectName = "";
            _project.isNew = true;
            return View(_project);
        }

        // редактировать проект
        public ActionResult projectDetails(long id)
        {
            project _project = new _Repository<project>().FindAll(p => p.ID == id).FirstOrDefault();

            if (_project == null)
            {
                TempData["resultMessage"] = "Нет такого проекта";
                return RedirectToAction("projects");
            }

            return View(_project);
        }

        [NonAction]
        public IformValuesDates processFormValuesDates
            (IformValuesDates refItem, int taskStatus = 0)
        {
            #region парсим данные формы
            
            DateTime tempDT;

            if (DateTime.TryParse(refItem.planStartString, out tempDT))
                refItem.planStart = tempDT;
            else
                refItem.planStart = null;

            if (DateTime.TryParse(refItem.factStartString, out tempDT))
                refItem.factStart = tempDT;
            else
                refItem.factStart = null;

            if (DateTime.TryParse(refItem.planFinishString, out tempDT))
                refItem.planFinish = tempDT;
            else
                refItem.planFinish = null;

            if (DateTime.TryParse(refItem.factFinishString, out tempDT))
                refItem.factFinish = tempDT;
            else
                refItem.factFinish = null;


            #endregion


            // план старт и план финиш всегда должны быть заданы для задачи
            if (typeof(task) == refItem.GetType())
            {
                if (refItem.planStart == null)
                    refItem.planStart = DateTime.Today;

                if (refItem.planStart == null)
                    refItem.planFinish = refItem.planStart;

                // если перевели в статус "Выполняется" и поле ФактСтарт не было заполнено 
                // - ставим текущую дату
                if (taskStatus == taskStatuses.Выполняется.GetHashCode())
                {
                    if (refItem.factStart == null)
                        refItem.factStart = DateTime.Now;

                }

                // если перевели в статус "Выполнена" и поле ФактФиниш не было заполнено 
                // - ставим текущую дату
                if (taskStatus == taskStatuses.Выполнена.GetHashCode())
                {
                    if (refItem.factFinish == null)
                        refItem.factFinish = DateTime.Now;

                }
            }

         

            // проверить даты на очередность
            if (refItem.planStart != null && refItem.planFinish != null)
            {
                if (refItem.planStart > refItem.planFinish)
                    refItem.planFinish = refItem.planStart;
            }

            if (refItem.factStart != null && refItem.factFinish != null)
            {
                if (refItem.factStart > refItem.factFinish)
                    refItem.factFinish = refItem.factStart;
            }

            return refItem;
        }

        // редактировать проект
        [HttpPost]
        public ActionResult projectDetails(project _project, FormCollection formValues)
        {

            _Repository<project> projectRepo = new _Repository<project>();
            project refItem = projectRepo.FindAll(p => p.ID == _project.ID).FirstOrDefault();
            bool insert = false;
            bool rightsEdit = true;
            if (refItem == null)
            {
                // создаем новый проект
                refItem = new project();
                refItem.owner_ID = new UserService().getCurrentUser().ID;
                insert = true;
            }
            else
                rightsEdit = refItem.rightsEditDelete;

            if (rightsEdit)
            {
                try
                {
                    UpdateModel(refItem);
                    refItem.projectStatus = Convert.ToInt32(formValues["projectStatus"]);
                    refItem.priority = Convert.ToInt32(formValues["priority"]);

                    // даты
                    refItem = (project)processFormValuesDates((IformValuesDates)refItem);

                    // Заказчик
                    if (formValues["projectCustomer_ID"] == "0")
                        refItem.customer_ID = null;
                    else
                        refItem.customer_ID = Convert.ToInt64(formValues["projectCustomer_ID"]);

                    if (insert)
                        projectRepo.InsertInstance(refItem);

                    projectRepo.Save();

                    ViewData["resultMessage"] = "Сохранили данные";
                    return View(refItem);
                }
                catch (Exception ex)
                {
                    ViewData["resultMessage"] = "Ошибка сохранения данных";
                    ExceptionUtility.LogException(logger, ex,
                        "[HttpPost] public ActionResult projectDetails(project _project)",
                        "Ошибка сохранения _project.ID: " + _project.ID);
                }
            }
            else
            {
                ViewData["resultMessage"] = "Ошибка сохранения данных. Недостаточно прав";   
            }

            return View(refItem);
        }

        // удалить проект
        public ActionResult DeleteProject(long id)
        {
            _Repository<project> projectRepo = new _Repository<project>();
            project _project = projectRepo.FindAll(p => p.ID == id).FirstOrDefault();

            if (_project == null)
            {
                TempData["resultMessage"] = "Нет такого проекта";
            }
            else
            {
                if (_project.rightsEditDelete)
                {
                    try
                    {
                        projectRepo.MarkForDeletion(_project);
                        projectRepo.Save();
                    }
                    catch (Exception ex)
                    {
                        ExceptionUtility.LogException(logger, ex,
                    "public ActionResult DeleteProject(long id)",
                    "Ошибка удаления _project.ID: " + _project.ID);
                        TempData["resultMessage"] = "Ошибка удаления проекта";
                    }

                } else
                    TempData["resultMessage"] = "Ошибка удаления проекта. Недостаточно прав";
            }

            return RedirectToAction("projects");
        }

        // Список проектов для выбранного заказчика
        // (в форме задачи)
        [HttpGet]
        public JsonResult projectsForCustomer(long taskCustomer_ID)
        {
            long currentUser_ID = new UserService().getCurrentUser().ID;
            IEnumerable<project> projects = new ProjectService().getProjectsList(currentUser_ID)
                    .Where(p => p.owner_ID == currentUser_ID);
                
                // Если заказчик выбран - отфильтровать по заказчику
                if (taskCustomer_ID != 0)
                { projects = projects.Where(p => p.customer_ID == taskCustomer_ID);}

                var projectsList = projects.Select(p => new { Value = p.ID, Text = p.projectName });
            return this.Json(projectsList, JsonRequestBehavior.AllowGet);
        }

        #endregion

        #region tasks

        // список задач
        public ActionResult tasks()
        {
            TaskService taskService = new TaskService();

            /* PRESERVE!!! НАСТРОЕНО ЧЕРЕЗ CRON! 
            // при обращении к списку задач запускаем процедуру 
            // формирования задач на основании периодических заданий
            taskService.formNewTasksOnPeriodicalTasks();*/

            
            
            tasksViewModel tVM = new tasksViewModel();

            taskService.loadTasksVMfilter(ref tVM); // чтение фильтра
            taskService.fillTasksViewModel(ref tVM); // наполнение списка задач
            taskService.addUserNamesToTasksViewModel(ref tVM); // добавить словарь имен пользователей

            ViewData["resultMessage"] = TempData["resultMessage"] + " " + tVM.resultMessage;

            return View(tVM);
        }

        // список задач - фильтр
        [HttpPost]
        public ActionResult tasks(FormCollection formValues, string confirmButton)
        {

            if (confirmButton == "Обновить")
            {

                long currentUser_ID = new UserService().getCurrentUser().ID;

                _Repository<userSetting> userSettingRepo = new _Repository<userSetting>();
                userSetting _userSetting = userSettingRepo.FindAll(p => p.user_ID == currentUser_ID).FirstOrDefault();
                if (_userSetting != null)
                {
                    _userSetting.tasks_customerID_filter = Convert.ToInt64(formValues["tasks_customerID_filter"]);
                    _userSetting.tasks_ownerID_filter = Convert.ToInt64(formValues["tasks_ownerID_filter"]);
                    _userSetting.tasks_performerID_filter = Convert.ToInt64(formValues["tasks_performerID_filter"]);

                    _userSetting.tasks_projectID_filter = Convert.ToInt64(formValues["tasks_projectID_filter"]);

                    _userSetting.tasks_isToPay_filter = formValues["isToPay_filter"].ToString() == "true,false";

                    DateTime dt;
                    // дата план начало
                    if (DateTime.TryParse(formValues["planStartFilterStringFrom"], out dt))
                        _userSetting.tasks_planStartFilterFrom = dt;
                    else
                    {
                        _userSetting.tasks_planStartFilterFrom = null;

                    }

                    // дата план финиш
                    if (DateTime.TryParse(formValues["planStartFilterStringTo"], out dt))
                        _userSetting.tasks_planStartFilterTo = dt;
                    else
                        _userSetting.tasks_planStartFilterTo = null;

                    // читаем из формы фильтр статусов задач
                    List<string> status_filter = new List<string>();
                    for (int i = 1; i <= 5; i++)
                    {
                        if (formValues["task_status" + i].ToString() != "false")
                            status_filter.Add(i.ToString());
                    }
                    _userSetting.tasks_status_filter = tools.getStringFromList(status_filter, ",");

                    // читаем из формы фильтр приоритетов задач
                    List<string> priority_filter = new List<string>();
                    for (int i = 1; i <= 4; i++)
                    {
                        if (formValues["task_priority" + i].ToString() != "false")
                            priority_filter.Add(i.ToString());
                    }
                    _userSetting.tasks_priority_filter = tools.getStringFromList(priority_filter, ","); ;

                    try
                    {
                        userSettingRepo.Save();
                    }
                    catch (Exception ex)
                    {
                        planerka.Common.ExceptionUtility.LogException(logger, ex,
                        "[HttpPost] public ActionResult tasks(FormCollection formValues, string confirmButton)", "Ошибка сохранения настроек пользователя");
                    }
                }

                
            }
            


            return RedirectToAction("tasks");
        }

        // создать задачу
        public ActionResult CreateTask()
        {
            long currentUser_ID = new UserService().getCurrentUser().ID;
            ProjectService projectService = new ProjectService();

            List<long> myProjectIDs = projectService.getProjectsList(currentUser_ID)
                .Where(p => p.owner_ID == currentUser_ID).Select(p => p.ID).ToList();

            if (myProjectIDs.Count() == 0)
            {
                TempData["resultMessage"] = "Сначала добавьте свой проект!";
                return RedirectToAction("tasks");
            }

            task _task = new task();
            _task.taskName = "";
            _task.project_ID = myProjectIDs.First();
            //_task.isNew = true;

            return View(_task);
        }

        // редактировать задачу
        public ActionResult taskDetails(long id)
        {
            TaskService taskService = new TaskService();
            task _task = taskService.getTasksList(new UserService().getCurrentUser().ID)
                .Where(p => p.ID == id).FirstOrDefault(); 
            // _Repository<task>().FindAll(p => p.ID == id).FirstOrDefault();

            if (_task == null)
            {
                TempData["resultMessage"] = "Нет такой задачи";
                return RedirectToAction("tasks");
            }

            _task.addPaymentDateString = DateTime.Today.ToShortDateString();

            #region показать информацию по методу проектирования

            _Repository<methodRecomendation> methodRecomendationRepo = new _Repository<methodRecomendation>();

            // для показа отбираем только те которые показывали не более одного раза
            List<methodRecomendation> methodRecomendations = methodRecomendationRepo.FindAll(p => p.task_ID == _task.ID && p.openQty < 2).ToList();
            if (methodRecomendations.Count > 0)
            {
                int minValue = methodRecomendations.Min(p => p.showQty);
                methodRecomendation _methodRecomendation = methodRecomendations.Where(p => p.showQty == minValue).First();
                _methodRecomendation.showQty++;
                try { methodRecomendationRepo.Save(); }
                catch { }

                methodInfo _methodInfo = taskService.getMethodInfoFromPlanerka(_methodRecomendation.method_ID);

                ViewData["methodInfo"] = _methodInfo;
            }
            #endregion

            return View(_task);
        }

        // удалить задачу
        public ActionResult DeleteTask(long id)
        {
            _Repository<task> taskRepo = new _Repository<task>();
            task _task = taskRepo.FindAll(p => p.ID == id).FirstOrDefault();

            if (_task == null)
            {
                TempData["resultMessage"] = "Нет такого проекта";
            }
            else
            {
                if (_task.rightsEditDelete)
                {
                    try
                    {
                        taskRepo.MarkForDeletion(_task);
                        taskRepo.Save();
                    }
                    catch (Exception ex)
                    {
                        ExceptionUtility.LogException(logger, ex,
                    "public ActionResult DeleteTask(long id)",
                    "Ошибка удаления _task.ID: " + _task.ID);

                        TempData["resultMessage"] = "Ошибка удаления задачи";
                    }
                }
                else
                    TempData["resultMessage"] = "Ошибка удаления задачи. Недостаточно прав";
            }

            return RedirectToAction("tasks");
        }

        // редактировать задачу
        [HttpPost]
        public ActionResult taskDetails(task _task, FormCollection formValues, string confirmButton, long? payment_ID)
        {
            task refItem = null;
            _Repository<task> taskRepo = new _Repository<task>();

            // удаление платежа
            if (confirmButton == "удалить")
            {
                #region deletePayment

                _Repository<payment> paymentRepo = new _Repository<payment>();
                
                payment _payment = paymentRepo.FindAll(p => p.ID == payment_ID).FirstOrDefault();
                if (_payment != null)
                {
                    refItem = taskRepo.FindAll(p => p.ID == _payment.task_ID).First();

                    if (refItem.rightsEditDelete)
                    {
                        try
                        {
                            paymentRepo.MarkForDeletion(_payment);
                            paymentRepo.Save();

                            ViewData["resultMessage"] = "Платеж удалён";
                        }
                        catch (Exception ex)
                        {
                            ExceptionUtility.LogException(logger, ex,
                                            "[HttpPost] public ActionResult taskDetails(task _task, FormCollection formValues, string confirmButton)",
                                            "Ошибка  удаления платежа _task.ID: " + _task.ID + ", payment_ID: " + payment_ID);

                            ViewData["resultMessage"] = "Ошибка удаления платежа";
                        }
                    } else
                        ViewData["registerPaymentsResults"] = "Недостаточно прав для редактирования";

                }
                else
                {
                    TempData["resultMessage"] = "Нет такого платежа";
                    return RedirectToAction("tasks");
                }

                #endregion
            }
            else
            {
                bool canSave = true;

                refItem = taskRepo.FindAll(p => p.ID == _task.ID).FirstOrDefault();

                // проверим права для существующей задачи
                if (refItem != null)
                    canSave = refItem.rightsEditDelete;


                if (confirmButton == "Сохранить")
                {
                    // не обновляется hiddden параметр ID
                    // http://stackoverflow.com/questions/3606087/why-mvc-html-hiddenfor-does-not-render-my-field
                    
                    if (canSave)
                    {
                        #region save

                        bool insert = false;
                        if (refItem == null)
                        {
                            // создаем новую задачу
                            refItem = new task();
                            insert = true;
                        }

                        try
                        {
                            UpdateModel(refItem);

                            if (refItem.taskName == null)
                                refItem.taskName = "";

                            refItem.taskStatus = Convert.ToInt32(formValues["taskStatus"]);
                            refItem.priority = Convert.ToInt32(formValues["priority"]);
                            refItem.project_ID = Convert.ToInt64(formValues["taskProject_ID"]);

                            if (formValues["periodicalType"] != null)
                            {
                                refItem.periodicalEveryMonthDay = null;
                                refItem.periodicalEveryWeekDay = null;

                                if (formValues["periodicalType"] == "monthDay")
                                    refItem.periodicalEveryMonthDay = Int32.Parse(formValues["periodicalEveryMonthDay"]);
                                else
                                    refItem.periodicalEveryWeekDay = Int32.Parse(formValues["periodicalEveryWeekDay"]);

                            }

                            // даты
                            refItem = (task)processFormValuesDates((IformValuesDates)refItem, refItem.taskStatus);

                            // Исполнитель
                            if (formValues["taskPerformer_ID"] == "0")
                                refItem.performer_ID = null;
                            else
                                refItem.performer_ID = Convert.ToInt64(formValues["taskPerformer_ID"]);

                            if (insert)
                                taskRepo.InsertInstance(refItem);

                            taskRepo.Save();

                            ViewData["resultMessage"] += "Сохранили данные";

                        }
                        catch (Exception ex)
                        {
                            ViewData["resultMessage"] = "Ошибка сохранения данных";
                            ExceptionUtility.LogException(logger, ex,
                                "[HttpPost] public ActionResult taskDetails(task _task)",
                                "Ошибка сохранения _task.ID: " + _task.ID);
                        }

                        #endregion
                    }
                        else
                            ViewData["registerPaymentsResults"] = "Недостаточно прав для редактирования";
                    }

                // внести платеж
                if (confirmButton == "Внести")
                {
                    if (refItem.rightsEditDelete)
                    {
                        #region registerPayment

                        _Repository<payment> paymentRepo = new _Repository<payment>();
                        payment _payment = new payment();

                        int sum = 0;

                        if (Int32.TryParse(formValues["addPayment"], out sum))
                        {
                            if (sum != 0)
                            {
                                _payment.task_ID = refItem.ID;
                                _payment.sumIn = sum > 0 ? sum : 0;
                                _payment.sumOut = sum < 0 ? -sum : 0;

                                DateTime dt;
                                if (!DateTime.TryParse(formValues["addPaymentDate"], out dt))
                                    dt = DateTime.Today;

                                _payment.timestamp = dt;
                                _payment.comment = formValues["addPaymentComment"].ToString();

                                try
                                {
                                    paymentRepo.InsertInstance(_payment);
                                    paymentRepo.Save();

                                    ViewData["resultMessage"] = "Платеж внесён";
                                }
                                catch (Exception ex)
                                {
                                    ExceptionUtility.LogException(logger, ex,
                                        "[HttpPost] public ActionResult taskDetails(task _task, FormCollection formValues, string confirmButton)",
                                        "Ошибка  регистрации платежа _task.ID: " + _task.ID);

                                    ViewData["resultMessage"] = "Ошибка регистрации платежа";
                                }
                            }
                            else
                            {
                                ViewData["resultMessage"] = "Введите сумму";
                            }
                        }
                        else
                        {
                            ViewData["resultMessage"] = "Введите сумму";
                        }

                        #endregion
                    }
                    else
                        ViewData["registerPaymentsResults"] = "Недостаточно прав для редактирования";
                }

                if (confirmButton == "Добавить сообщение")
                {
                    if (refItem.rightsView)
                    {
                        #region sendMessage

                        if (!String.IsNullOrEmpty(_task.addMessage))
                        {
                            long toUser_ID = 0;
                            Int64.TryParse(formValues["sendMessageTo"], out toUser_ID);
                            MessagesService messageService = new MessagesService();

                            messageService.addMessage
                                (_task.ID,
                                _task.addMessage,
                                _task.taskName,
                                new UserService().getCurrentUser().ID,
                                toUser_ID,
                                sendMail: true);
                        }

                        #endregion
                    }
                    else
                        ViewData["registerPaymentsResults"] = "Недостаточно прав для добавления сообщения";
                }

            }

            refItem.caption = "Редактируем задачу";
            return PartialView("_taskDetails", refItem);
        }

        
        [HttpPost]
        public ActionResult saveTaskStatus(long task_ID, int taskStatus)
        {
            return Json(new TaskService()
                .saveTaskStatus(task_ID, taskStatus));
        }

        // настройка показа колонок для таблицы "Задачи"
        [HttpPost]
        public ActionResult tuneTableColumns(tasksViewModel tVM)
        {
            long currentUser_ID = new UserService().getCurrentUser().ID;

            _Repository<userSetting> userSettingRepo = new _Repository<userSetting>();
            userSetting _userSetting = userSettingRepo.FindAll(p => p.user_ID == currentUser_ID).FirstOrDefault();
            if (_userSetting == null)
            {
                _userSetting = new userSetting();
                _userSetting.user_ID = currentUser_ID;

                // insert
                userSettingRepo.InsertInstance(_userSetting);
               
            }
            
            _userSetting.viewTableTasks_project = tVM.tuneTableColumns_project;
            _userSetting.viewTableTasks_roles = tVM.tuneTableColumns_roles;
            _userSetting.viewTableTasks_status = tVM.tuneTableColumns_status;
            _userSetting.viewTableTasks_priority = tVM.tuneTableColumns_priority;
            _userSetting.viewTableTasks_dates = tVM.tuneTableColumns_dates;
            _userSetting.viewTableTasks_sums = tVM.tuneTableColumns_sums;

            // save
            try { userSettingRepo.Save(); }
            catch (Exception ex) 
            {
                ExceptionUtility.LogException(logger, ex,
                    "[HttpPost] public ActionResult tuneTableColumns(tasksViewModel tVM)",
                    "Ошибка сохранения настроек показа колонок для таблицы \"Задачи\" currentUser_ID: " + currentUser_ID);
            }

            return RedirectToAction("tasks");
        }

        // быстрая оплата
        [HttpPost]
        public ActionResult quickPay(string task_IDs)
        {
            _Repository<task> taskRepo = new _Repository<task>();
            _Repository<payment> paymentRepo = new _Repository<payment>();
            string[] tasks = task_IDs.Split(',');
            long task_ID = 0;
            string result = "Платежи добавлены";
            foreach (var taskString in tasks)
            {
                if (Int64.TryParse(taskString, out task_ID))
                {
                    task _task = taskRepo.FindAll(p => p.ID == task_ID).FirstOrDefault();
                    if (_task != null)
                    {
                        if (_task.rightsEditDelete)
                        {
                            int sumTotalIn = paymentRepo.FindAll(p => p.task_ID == task_ID).Sum(p => p.sumIn ?? 0);
                            payment addPayment = new payment();
                            addPayment.timestamp = DateTime.Now;
                            addPayment.sumIn = _task.sumPlanned - sumTotalIn;
                            addPayment.project_ID = _task.project_ID;
                            addPayment.task_ID = task_ID;
                            addPayment.comment = "Быстрый платеж";

                            paymentRepo.InsertInstance(addPayment);
                            try 
                            {
                                paymentRepo.Save();
                            }
                            catch (Exception ex)
                            {
                                result = "Возникли ошибки при регистрации платежей";
                                ExceptionUtility.LogException(logger, ex,
                                    "[HttpPost] public ActionResult quickPay(string task_IDs)",
                                    "Ошибка регистрации быстрого платежа, task_ID: " + task_ID);
                            }

                        }
                    }
                }
                
            }
            
            TempData["resultMessage"] = result;

            return RedirectToAction("tasks");
        }

        #endregion

        #region backup and restore payments

        public ActionResult backupPayments()
        {
            long currentUser_ID = new UserService().getCurrentUser().ID;
            List<backupPayment> backupPayments = new PaymentService().getBackupPayments(currentUser_ID);

            return new exportToCSV<backupPayment>(backupPayments, ";", false, "excludeColumns") { FileDownloadName = "backupPayments.csv" };

            //return View();
        }

        public ActionResult restorePayments(FormCollection formValues)
        {
            string result = "Платежи добавлены";

            foreach (string upload in Request.Files)
            {
                string tempPath = Server.MapPath("~/images/temp/");
                string saveFileName = Guid.NewGuid().ToString();
                
                // очистим директорию с временными файлами
                graphics.emptyDirectory(tempPath);

                var postedFile = Request.Files[upload];
                if (postedFile.ContentLength > 0)
                {
                    // закачаем файл в директорию с временными файлами
                    Request.Files[upload].SaveAs(Path.Combine(tempPath, saveFileName));

                    try
                    {

                        // open the file "data.csv" which is a CSV file with headers
                        using (CsvReader csv =
                               new CsvReader(new StreamReader(Path.Combine(tempPath, saveFileName)), true))
                        {
                            int fieldCount = csv.FieldCount;

                            string[] headers = csv.GetFieldHeaders();
                            backupPayment _backupPayment;
                            PaymentService paymentService = new PaymentService();
                            long currentUser_ID = new UserService().getCurrentUser().ID;
                            while (csv.ReadNextRecord())
                            {
                                for (int i = 0; i < fieldCount; i++)
                                {
                                    string[] ID_sum = csv[i].Split(';');
                                    _backupPayment = new backupPayment();
                                    if (ID_sum.Count() > 1)
                                    {
                                        _backupPayment.payment_ID = Int64.Parse(ID_sum[0]);
                                        _backupPayment.sum = Int32.Parse(ID_sum[1]);

                                        // восстановить платеж
                                        paymentService.restorePayment(currentUser_ID, _backupPayment);

                                    }

                                }
                            }
                        }
                    }
                    catch
                    {
                        result = "Ошибка чтения файла архива платежей";
                    }

                }
            }
            TempData["resultMessage"] = result.ToString();
            return RedirectToAction("tasks");

        }

        #endregion


    }
}
